package cn.xnatural.demo.service;

import cn.xnatural.app.Bean;
import cn.xnatural.app.Lazier;
import cn.xnatural.app.ServerTpl;
import cn.xnatural.app.Utils;
import cn.xnatural.enet.event.EL;
import cn.xnatural.xnet.FileData;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.util.List;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

/**
 * 文件上传相关
 */
@Bean
public class FileUploader extends ServerTpl {
    // 文件上传的 本地保存目录
    protected final Lazier<String> _localDir = new Lazier<>(() -> {
        try {
            return new URL("file:" + (getStr("localDir", Utils.baseDir("../upload").getCanonicalPath()))).getFile();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    });
    // 上传文件 的访问url前缀
    protected final Lazier<URI> _accessUrlPrefix = new Lazier(() -> URI.create(getStr("accessUrlPrefix", ("//" + ep.fire("http.hp") + "/file/")) + "/").normalize());
    // 远程文件服务器url地址
    protected final Lazier<String> _remoteUrl       =  new Lazier<>(() -> getStr("remoteUrl", ""));


    @EL(name = "web.started")
    protected void init() {
        log.info("save upload file local dir: {}", _localDir.get());
        log.info("access upload file url prefix: {}", _accessUrlPrefix.get());
        if (_remoteUrl.get() != null && !_remoteUrl.get().isEmpty()) {log.info("remote file server http url: {}", _remoteUrl.get());}
    }


    /**
     * 映射 文件名 到一个 url
     * @param fileName 完整的文件名
     * @return 文件访问的url
     */
    public String toFullUrl(String fileName) { return _accessUrlPrefix.get().resolve(fileName).toString(); }


    /**
     * 查找文件
     * @param fileName 文件名
     * @return 文件
     */
    public File findFile(String fileName) { return new File(_localDir.get(), fileName); }


    /**
     * 根据文件名删除文件
     * @param fileName 文件名
     */
    @EL(name = "deleteFile", async = true)
    public void delete(String fileName) {
        File f = new File(_localDir.get(), fileName);
        if (f.exists()) f.delete();
        else log.warn("delete file '{}' not exists", fileName);
    }


    /**
     * 多文件 多线程保存
     * @param fds 多个文件数据
     */
    public List<FileData> save(List<FileData> fds) throws Exception {
        if (fds == null || fds.isEmpty()) return fds;

        // 并发上传
        for (Future<FileData> future : fds.stream().map(fd -> exec().submit(() -> save(fd))).collect(Collectors.toList())) {
            future.get();
        }
        return fds;
    }


    /**
     * 保存文件 文件流copy
     */
    public FileData save(FileData fd) throws Exception {
        if (fd == null) return null;
        if (_remoteUrl.get() == null || _remoteUrl.get().isEmpty()) {
            // 创建本地文件并写入
            File dir = new File(_localDir.get());
            dir.mkdirs();
            fd.transferTo(dir);
            log.info("Saved file: {}, originName: {}, size: " + fd.getSize(), dir.getAbsolutePath() + File.separator + fd.getFinalName(), fd.getOriginName());
        } else {  // http上传到远程文件服务
            // 1. 阿里OSS文件服务器例子
            // def oss = new OSSClient(endpoint, accessKeyId, accessKeySecret)
            // oss.putObject('path', fd.generatedName, fd.inputStream)

            // 2. 个人http文件服务器例子
//            Utils.http(_remoteUrl.get()).param("file", fd.getFinalName(), fd.getInputStream()).post();
        }
        return fd;
    }
}
